/*Graphic Liquid Cristal Display routines*/
#ifndef GLCD_H
#define GLCD_H

/*Header File*/
#include "semphr.h"
#include "..\common\errcode.h"
#include "..\common\osdata.h"

/*temporarily till I define ports*/
extern unsigned char dummy;

/*IO Ports definition*/
#ifdef KEIL_SAM7
#define PORT_INDEX          0
#define	DATA_GET()          ( (unsigned int) AT91F_PIO_GetInput( AT91C_BASE_PIOA ) >> PORT_INDEX ) & 0xFF
#define	DATA_SET(x)         AT91F_PIO_SetOutput( AT91C_BASE_PIOA, ( (unsigned int) (x & 0xFF) << PORT_INDEX ) ); \
                            AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, ( (unsigned int) ( (~x) & 0xFF) << PORT_INDEX ) )      
#define	DATA_IO_GET()       AT91F_PIO_CfgInput( AT91C_BASE_PIOA, ( (unsigned int) 0xFF << PORT_INDEX ) )
#define	DATA_IO_SET()       AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, ( (unsigned int) 0xFF << PORT_INDEX ) )
#define DATA_OP_DRAIN()     AT91C_BASE_PIOA->PIO_MDER =  ( (unsigned int) 0xFF << PORT_INDEX )
#define DATA_DIS_PULLUP()   AT91C_BASE_PIOA->PIO_PPUDR = ( (unsigned int) 0xFF << PORT_INDEX )
#endif

/*Booleans definitions*/
#define	IN              1
#define	OUT             0
#define	ON              1
#define	OFF             0
#define	GET             1
#define	SET             0
#define	TRUE            1
#define	FALSE           0

/*Cardinal Directions */
#define LEFT            0
#define RIGHT           1
#define UP              2
#define DOWN            3

/*Control Lines definition*/
#ifdef KEIL_SAM7
#define PIN_POS(z)          ((unsigned int) 0x1 <<  z)
#define CTRL_DIS_PULLUP(y)  AT91C_BASE_PIOA->PIO_PPUDR = PIN_POS(y)
#define CTRL_OP_DRAIN(y)    AT91C_BASE_PIOA->PIO_MDER = PIN_POS(y)
#define CTRL_IO(x,y)        CTRL_DIS_PULLUP(y);CTRL_OP_DRAIN(y);                            \
                            if (x) {AT91F_PIO_CfgInput( AT91C_BASE_PIOA, PIN_POS(y) );  }   \
                            else {AT91F_PIO_CfgOutput( AT91C_BASE_PIOA, PIN_POS(y) );   }
#define CTRL_SET(x,y)       if (x) {AT91F_PIO_SetOutput(AT91C_BASE_PIOA, PIN_POS(y) ); } \
                            else {AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, PIN_POS(y) ); }
#define CTRL_GET(x)         AT91F_PIO_IsInputSet( AT91C_BASE_PIOA, PIN_POS(x))
#endif

#define	CTRL_RS_IO(x)   CTRL_IO(x,27)
#define	CTRL_RS_SET(x)  CTRL_SET(x,27)
#define	CTRL_RS_GET()   CTRL_GET(27)

#define	CTRL_RW_IO(x)   CTRL_IO(x,10)
#define	CTRL_RW_SET(x)  CTRL_SET(x,10)
#define	CTRL_RW_GET()   CTRL_GET(10)

#define	CTRL_EN_IO(x)   CTRL_IO(x,11)
#define	CTRL_EN_SET(x)  CTRL_SET(x,11)
#define	CTRL_EN_GET()   CTRL_GET(11)

#define	CTRL_CS1_IO(x)  CTRL_IO(x,28)
#define	CTRL_CS1_SET(x) CTRL_SET(x,28)
#define	CTRL_CS1_GET()  CTRL_GET(28)

#define	CTRL_CS2_IO(x)  CTRL_IO(x,9)
#define	CTRL_CS2_SET(x) CTRL_SET(x,9)
#define	CTRL_CS2_GET()  CTRL_GET(9)

#define	CTRL_RES_IO(x)  CTRL_IO(x,8)
#define	CTRL_RES_SET(x) CTRL_SET( !x, 8) /*Reset is ACtive LOW*/
#define	CTRL_RES_GET()  !CTRL_GET(8)

/*Screen Specific Sizes definition*/
#define	SIZE_CS1_X_MAX  ( unsigned portCHAR ) 63
#define	SIZE_CS2_X_MAX  ( unsigned portCHAR ) 127
#define	SIZE_BNK_Y_MAX  ( unsigned portCHAR ) 7
#define	SIZE_X_SCR_MAX  SIZE_CS2_X_MAX + 1
#define	SIZE_Y_SCR_MAX  ( SIZE_BNK_Y_MAX + 1 ) * 8

/*KS0108 Chipset Instructions*/
#define	INSTR_BUSY      0x80
#define	INSTR_DISP_ON   0x3F
#define	INSTR_DISP_OFF  0x3E
#define	INSTR_SET_RAM_0 0xC0
#define	INSTR_SET_X     0x40
#define	INSTR_SET_Y     0xB8

/*cGlcdHandle Control Bits*/
#define	CTRL_CMD_WR     0x00
#define	CTRL_DATA_WR    0x01
#define	CTRL_CMD_RD     0x02
#define	CTRL_DATA_RD    0x03
#define	CTRL_CS_POSX    0x04
#define	CTRL_CS_1       0x08
#define	CTRL_CS_2       0x10
#define	CTRL_CS_12      CTRL_CS_1 | CTRL_CS_2
#define	CTRL_W_DUMMY    0x20

/*Pixel coloring methods*/
#define	PX_COMB_OFF     ( unsigned portCHAR ) 0
#define	PX_COMB_ON      ( unsigned portCHAR ) 1
#define	PX_COMB_NOT     ( unsigned portCHAR ) 2

/*Bipmap combining method*/
#define	PX_COMB_AND     ( unsigned portCHAR ) 0
#define	PX_COMB_OR      ( unsigned portCHAR ) 1
#define	PX_COMB_XOR     ( unsigned portCHAR ) 2
#define	PX_COMB_PASTE   ( unsigned portCHAR ) 3
#define	PX_COMB_NPASTE  ( unsigned portCHAR ) 4
#define	PX_COMB_DATA    ( unsigned portCHAR ) 5
#define	PX_COMB_NDATA   ( unsigned portCHAR ) 6
#define	PX_COMB_XDATA   ( unsigned portCHAR ) 7

/*Default text parameters*/
#define	DEFAULT_TAB     4 

/*Type Cast*/
#ifdef MPLAB_PIC18F_PORT
#define STRING_CAST ( const portCHAR * const )
#else
#define STRING_CAST
#endif

/*Types Definition, unions*/
#ifdef KEIL_SAM7
    #pragma anon_unions
#endif
typedef union
{
    unsigned portSHORT cshort;
    struct 
    {
        unsigned portCHAR byteLow, byteHi; 
    };
} shortWord;

typedef union
{
    unsigned portLONG clong;
    struct 
    {
        shortWord shortLow, shortHi;
    };
} longWord;

typedef struct
{
    unsigned portCHAR bit:1, getSet:1, :6;
    unsigned portCHAR *data, index, size;
} tGlcdbuffer, *pGlcdbuffer;

typedef struct
{
    unsigned portCHAR    data;
    unsigned portCHAR    dataCommand:1, readWrite:1, cs4PosX:1, cS1:1, cS2:1, wDummy:1,:2;
} tGlcdDataControl, *pGlcdDataControl;

typedef struct
{
    unsigned portCHAR    x, y;
} tGlcdSizePos, *pGlcdSizePos;

typedef struct
{
    unsigned portCHAR color:3, limited:1, optimized:1, getSet:1, :2;
} tGlcdParameter, *pGlcdParameter;

typedef struct
{
    tGlcdSizePos size, offset;
    tGlcdParameter param;
    const unsigned portCHAR *data;
} tGlcdFillData, *pGlcdFillData;

typedef struct
{
    tGlcdSizePos pos;
    tGlcdParameter param;
} tGlcdPixel, *pGlcdPixel;

typedef struct
{
    tGlcdSizePos posIni, posFin;
    tGlcdParameter param;
    tGlcdbuffer buffer;
} tGlcdLine, *pGlcdLine;

typedef struct
{
    tGlcdSizePos posIni, posFin;
    tGlcdParameter param;
    tGlcdbuffer buffer;
} tGlcdRectangle, *pGlcdRectangle;

typedef struct
{
    tGlcdSizePos pos;
    unsigned portCHAR radio;
    tGlcdParameter param;
} tGlcdCircle, *pGlcdCircle;

typedef struct
{
    tGlcdSizePos pos;
    tGlcdParameter param;
    unsigned int size;
    pGlcdSizePos data;
} tGlcdFloodFill, *pGlcdFloodFill;

typedef struct
{
    tGlcdSizePos pos, size;
    tGlcdParameter param;
    struct
    {
        tGlcdSizePos size;
        tGlcdSizePos offset;
        const unsigned portCHAR *data;
    } source;
} tGlcdBitmapSet, *pGlcdBitmapSet;

typedef struct
{
    tGlcdSizePos pos, size;
    tGlcdParameter param;
    unsigned portCHAR *data;
} tGlcdBitmapGet, *pGlcdBitmapGet;

typedef struct
{
    struct { tGlcdSizePos pos, size; } window;
    struct
    {
        tGlcdSizePos pos;
        tGlcdParameter param;
        unsigned portCHAR tabspace;
        const portCHAR *data;
    } string;
    struct
    {
        tGlcdSizePos size;
        const unsigned portCHAR *data;    
    } font;
} tGlcdText, *pGlcdText;

/*Global Var*/
typedef struct
{
    tGlcdSizePos bytePos, pixelPos;
    tOSData mutex, event;
    tOSData mutex2, event2;
    tOSData mutex3, event3;
} tGlcdData;

/*Constants*/						 

/*Variable Definition*/
extern tGlcdData xGlcdData;

/*Functionality enabling*/
#define ENABLE_FILLSCR_DOUBLECS   FALSE /*If Enabled, it searches for 2^N source in X to perform double CS enabling*/
#define ENABLE_FILLSCR_DISPOFF    FALSE /*If Enabled, at the beginning of the fillscreen procedure, the display is soft powered of*/
#define FORCE_FILLSCR_INIT        TRUE  /*If Enabled, a first call to FillScr must be done to soft enable screen an thus avoiding unwanted images*/
#define ENABLE_LINE_REDIRECTION   FALSE /*If Enabled, the direction of line drawing is always form left to right to help LCD logic*/

/*Public Functions and procedures Declaration*/
extern void vGlcdInit( void );
extern void vGlcdGetSetBitArray ( pGlcdbuffer buffer );
extern unsigned portCHAR cGlcdFillScr( pGlcdFillData fillData );
extern unsigned portCHAR cGlcdPixel( pGlcdPixel pixel );
extern unsigned portCHAR cGlcdLine( pGlcdLine line );
extern unsigned portCHAR cGlcdFloodFill( pGlcdFloodFill floodFill );
extern unsigned portCHAR cGlcdRectangle( pGlcdRectangle rectangle);
extern unsigned portCHAR cGlcdCircle( pGlcdCircle circle );
extern unsigned portCHAR cGlcdBitmapSet( pGlcdBitmapSet bitmap );
extern unsigned portCHAR cGlcdBitmapGet( pGlcdBitmapGet bitmap );
extern unsigned portCHAR cGlcdPrintf( pGlcdText text );

/*Macro definitions*/
#define vGlcdWait()             portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();\
                                portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP();portNOP()
#define vGlcdUpdateData(x)      cDataCtrl[ 0 ] = x
#define vGlcdUpdateCtrl(y)      cDataCtrl[ 1 ] = y
#define vGlcdSetData(x)         vGlcdUpdateData(x); cGlcdHandle( ( pGlcdDataControl ) cDataCtrl )
#define vGlcdSetCtrl(y)         vGlcdUpdateCtrl(y); cGlcdHandle( ( pGlcdDataControl ) cDataCtrl )
#define vGlcdSetDataCtrl(x,y)   vGlcdUpdateData(x); vGlcdUpdateCtrl(y); cGlcdHandle( ( pGlcdDataControl ) cDataCtrl )
#define vGlcdDispOff()          cGlcdHandle( ( pGlcdDataControl ) cDataCtrlDispOff )
#define vGlcdDispOn()           cGlcdHandle( ( pGlcdDataControl ) cDataCtrlDispOn )
#define vGlcdSetRam0()          cGlcdHandle( ( pGlcdDataControl ) cDataCtrlSetRam0 )
#define vGlcdSetX0()            cGlcdHandle( ( pGlcdDataControl ) cDataCtrlSetX0 )
#define cGlcdReadByte()         cGlcdHandle( ( pGlcdDataControl ) cDataCtrlReadByte )
#define vGlcdGotoXY(x,y)        vGlcdGotoX(x); vGlcdGotoY(y)
#define xGlcdGetDefTAB(x)       x * DEFAULT_TAB  
#define xGlcdGetTABSize()       ( ( ( text->string.pos.x / text->string.tabspace ) + 1 ) * text->string.tabspace ) - text->string.pos.x
#define vGlcdNewLine()          text->string.pos.x = 0; text->string.pos.y += text->font.size.y
#define vGlcdiCls()             text->string.pos.x = 0; text->string.pos.y = 0;
#define vGlcdCls(z)             z.string.pos.x = 0; z.string.pos.y = 0;
#define vGlcdClrScr()           data = '\f'; vGlcdiCls(); bitmap.size = text->window.size; bitmap.source.size.x = 1; bitmap.source.size.y = 8; bitmap.source.data = &ZERO
#define xGlcdSizeof(obj, pos)   ( obj.posFin.pos > obj.posIni.pos ) ? (obj.posFin.pos - obj.posIni.pos) : (obj.posIni.pos - obj.posFin.pos)
#define vGlcdSetBlockTime(x)	xGlcdData.event.xBlockTime = xGlcdData.event2.xBlockTime = 	xGlcdData.event3.xBlockTime = x

#endif /*GLCD_H*/
